/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Persistencia;

import Persistencia.exceptions.NonexistentEntityException;
import Persistencia.exceptions.PreexistingEntityException;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import motoressa.Taller;
import motoressa.InformeDeDiagnostico;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.transaction.UserTransaction;
import motoressa.Tecnico;

/**
 *
 * @author HP
 */
public class TecnicoJpaController implements Serializable {

    public TecnicoJpaController(UserTransaction utx, EntityManagerFactory emf) {
        this.utx = utx;
        this.emf = emf;
    }
    private UserTransaction utx = null;
    private EntityManagerFactory emf = null;

    public TecnicoJpaController() {
        emf=Persistence.createEntityManagerFactory("MotoresSAPU");
    }
    

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Tecnico tecnico) throws PreexistingEntityException, Exception {
        if (tecnico.getMisInformes() == null) {
            tecnico.setMisInformes(new ArrayList<InformeDeDiagnostico>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Taller miTaller = tecnico.getMiTaller();
            if (miTaller != null) {
                miTaller = em.getReference(miTaller.getClass(), miTaller.getCodigo());
                tecnico.setMiTaller(miTaller);
            }
            List<InformeDeDiagnostico> attachedMisInformes = new ArrayList<InformeDeDiagnostico>();
            for (InformeDeDiagnostico misInformesInformeDeDiagnosticoToAttach : tecnico.getMisInformes()) {
                misInformesInformeDeDiagnosticoToAttach = em.getReference(misInformesInformeDeDiagnosticoToAttach.getClass(), misInformesInformeDeDiagnosticoToAttach.getCodigo());
                attachedMisInformes.add(misInformesInformeDeDiagnosticoToAttach);
            }
            tecnico.setMisInformes(attachedMisInformes);
            em.persist(tecnico);
            if (miTaller != null) {
                miTaller.getMisTecnicos().add(tecnico);
                miTaller = em.merge(miTaller);
            }
            for (InformeDeDiagnostico misInformesInformeDeDiagnostico : tecnico.getMisInformes()) {
                Tecnico oldMiTecnicoOfMisInformesInformeDeDiagnostico = misInformesInformeDeDiagnostico.getMiTecnico();
                misInformesInformeDeDiagnostico.setMiTecnico(tecnico);
                misInformesInformeDeDiagnostico = em.merge(misInformesInformeDeDiagnostico);
                if (oldMiTecnicoOfMisInformesInformeDeDiagnostico != null) {
                    oldMiTecnicoOfMisInformesInformeDeDiagnostico.getMisInformes().remove(misInformesInformeDeDiagnostico);
                    oldMiTecnicoOfMisInformesInformeDeDiagnostico = em.merge(oldMiTecnicoOfMisInformesInformeDeDiagnostico);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findTecnico(tecnico.getDni()) != null) {
                throw new PreexistingEntityException("Tecnico " + tecnico + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Tecnico tecnico) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Tecnico persistentTecnico = em.find(Tecnico.class, tecnico.getDni());
            Taller miTallerOld = persistentTecnico.getMiTaller();
            Taller miTallerNew = tecnico.getMiTaller();
            List<InformeDeDiagnostico> misInformesOld = persistentTecnico.getMisInformes();
            List<InformeDeDiagnostico> misInformesNew = tecnico.getMisInformes();
            if (miTallerNew != null) {
                miTallerNew = em.getReference(miTallerNew.getClass(), miTallerNew.getCodigo());
                tecnico.setMiTaller(miTallerNew);
            }
            List<InformeDeDiagnostico> attachedMisInformesNew = new ArrayList<InformeDeDiagnostico>();
            for (InformeDeDiagnostico misInformesNewInformeDeDiagnosticoToAttach : misInformesNew) {
                misInformesNewInformeDeDiagnosticoToAttach = em.getReference(misInformesNewInformeDeDiagnosticoToAttach.getClass(), misInformesNewInformeDeDiagnosticoToAttach.getCodigo());
                attachedMisInformesNew.add(misInformesNewInformeDeDiagnosticoToAttach);
            }
            misInformesNew = attachedMisInformesNew;
            tecnico.setMisInformes(misInformesNew);
            tecnico = em.merge(tecnico);
            if (miTallerOld != null && !miTallerOld.equals(miTallerNew)) {
                miTallerOld.getMisTecnicos().remove(tecnico);
                miTallerOld = em.merge(miTallerOld);
            }
            if (miTallerNew != null && !miTallerNew.equals(miTallerOld)) {
                miTallerNew.getMisTecnicos().add(tecnico);
                miTallerNew = em.merge(miTallerNew);
            }
            for (InformeDeDiagnostico misInformesOldInformeDeDiagnostico : misInformesOld) {
                if (!misInformesNew.contains(misInformesOldInformeDeDiagnostico)) {
                    misInformesOldInformeDeDiagnostico.setMiTecnico(null);
                    misInformesOldInformeDeDiagnostico = em.merge(misInformesOldInformeDeDiagnostico);
                }
            }
            for (InformeDeDiagnostico misInformesNewInformeDeDiagnostico : misInformesNew) {
                if (!misInformesOld.contains(misInformesNewInformeDeDiagnostico)) {
                    Tecnico oldMiTecnicoOfMisInformesNewInformeDeDiagnostico = misInformesNewInformeDeDiagnostico.getMiTecnico();
                    misInformesNewInformeDeDiagnostico.setMiTecnico(tecnico);
                    misInformesNewInformeDeDiagnostico = em.merge(misInformesNewInformeDeDiagnostico);
                    if (oldMiTecnicoOfMisInformesNewInformeDeDiagnostico != null && !oldMiTecnicoOfMisInformesNewInformeDeDiagnostico.equals(tecnico)) {
                        oldMiTecnicoOfMisInformesNewInformeDeDiagnostico.getMisInformes().remove(misInformesNewInformeDeDiagnostico);
                        oldMiTecnicoOfMisInformesNewInformeDeDiagnostico = em.merge(oldMiTecnicoOfMisInformesNewInformeDeDiagnostico);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                String id = tecnico.getDni();
                if (findTecnico(id) == null) {
                    throw new NonexistentEntityException("The tecnico with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(String id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Tecnico tecnico;
            try {
                tecnico = em.getReference(Tecnico.class, id);
                tecnico.getDni();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The tecnico with id " + id + " no longer exists.", enfe);
            }
            Taller miTaller = tecnico.getMiTaller();
            if (miTaller != null) {
                miTaller.getMisTecnicos().remove(tecnico);
                miTaller = em.merge(miTaller);
            }
            List<InformeDeDiagnostico> misInformes = tecnico.getMisInformes();
            for (InformeDeDiagnostico misInformesInformeDeDiagnostico : misInformes) {
                misInformesInformeDeDiagnostico.setMiTecnico(null);
                misInformesInformeDeDiagnostico = em.merge(misInformesInformeDeDiagnostico);
            }
            em.remove(tecnico);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Tecnico> findTecnicoEntities() {
        return findTecnicoEntities(true, -1, -1);
    }

    public List<Tecnico> findTecnicoEntities(int maxResults, int firstResult) {
        return findTecnicoEntities(false, maxResults, firstResult);
    }

    private List<Tecnico> findTecnicoEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select object(o) from Tecnico as o");
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Tecnico findTecnico(String id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Tecnico.class, id);
        } finally {
            em.close();
        }
    }

    public int getTecnicoCount() {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select count(o) from Tecnico as o");
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
